Skip to content

feat(metrics): Add additional metrics#1572

Draft
rkuris wants to merge 4 commits intomainfrom
rkuris/metrics-improvements-2
Draft

feat(metrics): Add additional metrics#1572
rkuris wants to merge 4 commits intomainfrom
rkuris/metrics-improvements-2

Conversation

@rkuris
Copy link
Member

@rkuris rkuris commented Dec 17, 2025

Why this should be merged

  • Added firewood.revisions.reaped counter with mode label (with_rootstore|without_rootstore)
  • Added firewood.revisions.reaping_failed counter on Arc::try_unwrap failure
  • Added firewood.revisions.historical_queries counter with source label (memory|rootstore)

How this works

Pretty obvious

How this was tested

Marked DO NOT MERGE until we can properly test it. Depends on getting metrics working.

Replace all direct uses of counter! with firewood_counter! to ensure
metric descriptions are registered consistently. The firewood_counter!
macro automatically handles description registration using Once to
avoid duplicate registrations while providing better documentation
for all metrics.

Updated files:
- firewood/src/db.rs: proposal counter
- firewood/src/merkle/mod.rs: insert/remove counters
- storage/src/linear/memory.rs: read counter
- storage/src/linear/filebacked.rs: cache and IO counters
- ffi/src/handle.rs: FFI batch/commit/cached_view counters
- ffi/src/proposal.rs: FFI propose counters
- ffi/src/lib.rs: FFI commit counters
- ffi/src/proofs/range.rs: FFI merge counters
Previously, the firewood_gauge! macro was incorrectly calling
metrics::describe_counter! instead of metrics::describe_gauge!,
which would register gauge metrics with incorrect descriptions.

This commit:
- Fixes the macro to properly call describe_gauge! for both
  labeled and unlabeled gauge variants
- Updates existing gauge usage in manager.rs to use firewood_gauge!
  macro with proper descriptions
- Adds comprehensive tests for both firewood_counter! and
  firewood_gauge! macros
- Updates documentation to include .set() method in gauge usage
- Add firewood.proposals.outstanding gauge in RevisionManager on add/cleanup
- Add firewood.proposals.discarded counter during proposal cleanup
- Add firewood.proposals.based_on_proposal counter when proposing on a proposal
- Add firewood.proposals.reparented counter on commit reparent

All metrics use firewood_counter!/firewood_gauge! macros and avoid allocations.
Verified with cargo check/nextest across workspace.
…rics

- Add firewood.revisions.reaped counter with mode label (with_rootstore|without_rootstore)
- Add firewood.revisions.reaping_failed counter on Arc::try_unwrap failure
- Add firewood.revisions.historical_queries counter with source label (memory|rootstore)

Existing gauges (active/max revisions) kept updated. Verified via cargo check/nextest.
@github-actions
Copy link

Metrics Change Detection ⚠️

This PR contains changes related to metrics:

-            counter!("firewood.ffi.commit_ms").increment(commit_time.as_millis());
+            firewood_counter!(
-        counter!("firewood.ffi.batch_ms").increment(start_time.elapsed().as_millis());
-        counter!("firewood.ffi.batch").increment(1);
+        firewood_counter!("firewood.ffi.batch_ms", "FFI batch timing in milliseconds")
+        firewood_counter!("firewood.ffi.batch", "Number of FFI batch operations").increment(1);
-            counter!("firewood.ffi.cached_view.miss").increment(1);
+            firewood_counter!(
-            counter!("firewood.ffi.cached_view.hit").increment(1);
+            firewood_counter!(
-            metrics::counter!("firewood.ffi.commit_ms").increment(commit_time.as_millis());
-            metrics::counter!("firewood.ffi.commit").increment(1);
+            firewood_counter!(
+            firewood_counter!("firewood.ffi.commit", "Number of FFI commit operations")
-            metrics::counter!("firewood.ffi.commit_ms").increment(commit_time.as_millis());
-            metrics::counter!("firewood.ffi.merge").increment(1);
+            firewood_counter!(
+            firewood_counter!("firewood.ffi.merge", "Number of FFI merge operations").increment(1);
-        counter!("firewood.ffi.propose_ms").increment(propose_time.as_millis());
-        counter!("firewood.ffi.propose").increment(1);
+        firewood_counter!(
+        firewood_counter!("firewood.ffi.propose", "Number of FFI propose operations").increment(1);
-            proposals: counter!("firewood.proposals"),
+            proposals: firewood_counter!("firewood.proposals", "Number of proposals created"),
-        describe_counter!("firewood.proposals", "Number of proposals created");
+        firewood_storage::firewood_counter!(
+                        firewood_counter!(
+                        firewood_counter!(
+                firewood_counter!(
-            gauge!("firewood.active_revisions").set(self.in_memory_revisions.read().len() as f64);
-            gauge!("firewood.max_revisions").set(self.max_revisions as f64);
+            firewood_gauge!(
+            firewood_gauge!(
+                firewood_counter!(
+            firewood_gauge!(
+        firewood_gauge!(
+            firewood_counter!(
+        firewood_counter!(
-                counter!("firewood.insert", "merkle" => "update").increment(1);
+                firewood_counter!("firewood.insert", "Number of merkle insert operations", "merkle" => "update").increment(1);
-                counter!("firewood.insert", "merkle"=>"above").increment(1);
+                firewood_counter!("firewood.insert", "Number of merkle insert operations", "merkle"=>"above").increment(1);
-                            counter!("firewood.insert", "merkle"=>"below").increment(1);
+                            firewood_counter!("firewood.insert", "Number of merkle insert operations", "merkle"=>"below").increment(1);
-                        counter!("firewood.insert", "merkle"=>"split").increment(1);
+                        firewood_counter!("firewood.insert", "Number of merkle insert operations", "merkle"=>"split").increment(1);
-                counter!("firewood.insert", "merkle" => "split").increment(1);
+                firewood_counter!("firewood.insert", "Number of merkle insert operations", "merkle" => "split").increment(1);
-            counter!("firewood.remove", "prefix" => "false", "result" => "nonexistent")
+            firewood_counter!("firewood.remove", "Number of merkle remove operations", "prefix" => "false", "result" => "nonexistent")
-            counter!("firewood.remove", "prefix" => "false", "result" => "success").increment(1);
+            firewood_counter!("firewood.remove", "Number of merkle remove operations", "prefix" => "false", "result" => "success").increment(1);
-            counter!("firewood.remove", "prefix" => "false", "result" => "nonexistent")
+            firewood_counter!("firewood.remove", "Number of merkle remove operations", "prefix" => "false", "result" => "nonexistent")
-            counter!("firewood.remove", "prefix" => "true", "result" => "nonexistent").increment(1);
+            firewood_counter!("firewood.remove", "Number of merkle remove operations", "prefix" => "true", "result" => "nonexistent").increment(1);
-        counter!("firewood.remove", "prefix" => "true", "result" => "success")
+        firewood_counter!("firewood.remove", "Number of merkle remove operations", "prefix" => "true", "result" => "success")
-        counter!("firewood.read_node", "from" => "file").increment(1);
+        firewood_counter!("firewood.read_node", "Number of node reads", "from" => "file")
-        counter!("firewood.cache.node", "mode" => mode, "type" => if cached.is_some() { "hit" } else { "miss" })
+        firewood_counter!("firewood.cache.node", "Number of node cache operations", "mode" => mode, "type" => if cached.is_some() { "hit" } else { "miss" })
-        counter!("firewood.cache.freelist", "type" => if cached.is_some() { "hit" } else { "miss" }).increment(1);
+        firewood_counter!("firewood.cache.freelist", "Number of freelist cache operations", "type" => if cached.is_some() { "hit" } else { "miss" }).increment(1);
-        counter!("firewood.io.read_ms").increment(elapsed.as_millis());
-        counter!("firewood.io.read").increment(1);
+        firewood_counter!("firewood.io.read_ms", "IO read timing in milliseconds")
+        firewood_counter!("firewood.io.read", "Number of IO read operations").increment(1);
-        counter!("firewood.read_node", "from" => "memory").increment(1);
+        firewood_counter!("firewood.read_node", "Number of node reads", "from" => "memory")
-                metrics::describe_counter!($name, $desc);
+                metrics::describe_gauge!($name, $desc);
-                metrics::describe_counter!($name, $desc);
+                metrics::describe_gauge!($name, $desc);
+        let counter = firewood_counter!("test.counter.simple", "A simple test counter");
+            firewood_counter!("test.counter.labeled", "A labeled test counter", "env" => "test");
+        let gauge = firewood_gauge!("test.gauge.simple", "A simple test gauge");
+            firewood_gauge!("test.gauge.labeled", "A labeled test gauge", "env" => "test");
+            let counter = firewood_counter!("test.counter.multi", "Multi-call test counter");
+            let gauge = firewood_gauge!("test.gauge.multi", "Multi-call test gauge");
+            firewood_counter!(

However, the dashboard was not modified.

You may need to update benchmark/Grafana-dashboard.json accordingly.


This check is automated to help maintain the dashboard.

@rkuris rkuris changed the title Rkuris/metrics improvements 2 feat(metrics): Add additional metrics Dec 29, 2025
@rkuris rkuris self-assigned this Dec 29, 2025
@rkuris rkuris added DO NOT MERGE This PR is not meant to be merged in its current state observability logging, tracing and metrics labels Dec 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DO NOT MERGE This PR is not meant to be merged in its current state observability logging, tracing and metrics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant